// package com.ifp.opengate.boot.filter;
//
// import java.time.LocalDateTime;
// import java.time.format.DateTimeFormatter;
// import java.util.Map;
// import java.util.Random;
//
// import org.apache.commons.lang3.StringUtils;
// import org.springframework.beans.factory.annotation.Autowired;
// import org.springframework.cloud.gateway.filter.GatewayFilterChain;
// import org.springframework.cloud.gateway.filter.GlobalFilter;
// import org.springframework.core.Ordered;
// import org.springframework.stereotype.Component;
// import org.springframework.web.server.ServerWebExchange;
//
// import com.alibaba.fastjson.JSONObject;
// import com.ifp.adapter.common.AdapterCanstants;
// import com.ifp.core.context.ClogicContext;
// import com.ifp.core.util.Base64;
// import com.ifp.core.util.StringUtil;
// import com.ifp.opengate.boot.bean.access.IPBlackAndWhiteBean;
// import com.ifp.opengate.boot.constants.Constants;
// import com.ifp.opengate.boot.emum.ErrorEnum;
// import com.ifp.opengate.boot.exception.AccessControlException;
// import com.ifp.opengate.boot.task.ApiDeployTask;
// import com.ifp.opengate.boot.utils.RedisUtils;
// import com.ifp.opengate.boot.utils.WhiteListCaheUtil;
//
// import reactor.core.publisher.Mono;
//
/// **
// * 项目名：ifp-gateway <br>
// * 包名：com.ifp.opengate.boot.filter <br>
// * 类名：Oauth2GlobalFilter <br>
// * 描述：
// *
// * @author Suremotoo
// * @create 2021-06-15 14:50
// */
//
//// @Component
// public class Oauth2GlobalFilter implements GlobalFilter, Ordered {
//
// @Autowired
// private ApiDeployTask apiDeployTask;
//
// /*
// * 黑白应用bean缓存
// */
//
// @Autowired
// private IPBlackAndWhiteBean ipBlackAndWhiteBean;
//
// @Autowired
// private RedisUtils redisUtils;
//
// @Override
// public int getOrder() {
// // 在黑白名单过滤器、验签解密过滤器、验证合作方信息过滤器之后
// return -4;
// }
//
// @SuppressWarnings("unchecked")
// @Override
// public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// // Trace.logInfo(Trace.MODULE_INTERCEPTOR, "execute interceptor{}'s preHandle() begin ", this);
//
// ClogicContext clogicContext = (ClogicContext)exchange.getAttributes().get("clContext");
// // 应用id
// String appId = (String)clogicContext.dataMap.get(Constants.APP_ID);
// Map<String, Object> dataMap = clogicContext.getDataMap();
// // 请求报文头
// Map<String, Object> headerMap = (Map<String, Object>)dataMap.get(AdapterCanstants.HEADER);
//
// // 获取api信息缓存
// String apiVersion = (String)clogicContext.getValue(Constants.VERSION);
// String transCode = clogicContext.getTransCode();
// String apiInfoKey = Constants.API_INFO_PREFIX + transCode;
// Map<Object, Object> apiInfo = apiDeployTask.getApiInfoMap()
// .get(Constants.OPEN_GATE_CACHE_NAME + "_" + apiInfoKey + Constants.BOTTOM_LINE + apiVersion);
//
// // 1.该接口是否进行OAUTH验证,0不需要授权,1需要授权;在白名单内无需OAuth验证;
// // Trace.logInfo(Trace.MODULE_COMMON, "1.判断接口是否需要进行OAuth认证");
// if ((apiInfo != null && "0".equals(apiInfo.get("oauth") + "")) || WhiteListCaheUtil.getCacheCheckWhiteFromBean(
// ipBlackAndWhiteBean.getAppWhtelist(), appId, "OAuthGlobalFilter", clogicContext)) {
// // Trace.logInfo(Trace.MODULE_INTERCEPTOR, "白名单跳过OAuthGlobalFilter----------------");
// return chain.filter(exchange);
// }
// // Trace.logInfo(Trace.MODULE_COMMON, "2.验证用户是否登录（token有效性校验）");
// // 2.验证是否登录（token是否有效）redis
// String userId = (String)headerMap.get("userId");
// if (StringUtils.isBlank(userId) || "null".equals(userId)) {
// throw new AccessControlException(ErrorEnum.oauthNotFoundReqUserIdError.code(),
// ErrorEnum.oauthNotFoundReqUserIdError.msg());
// }
//
// // 参数加密
// String secretStr = new String(Base64.encode(appId.getBytes())); // MD5.getInstance().getMD5String( + "@" +
// // h5OpenId);
// // 访问Token
// String accessToken = (String)headerMap.get("accessToken");
// // 2.1没有token，返回授权登录页面
// if (StringUtils.isBlank(accessToken) || "null".equals(accessToken)) {
// throw new AccessControlException(ErrorEnum.oauthNotFoundReqTokenError.code(),
// ErrorEnum.oauthNotFoundReqTokenError.msg());
// }
// final String validTokenKey = "opengate_oauth_atoken_" + appId + "@%@" + userId;
// // Trace.logInfo(Trace.MODULE_COMMON, validTokenKey);
// // 包含了token信息及服务授权信息 accessToken@%@appId@%@userId@%@param
// //
// "NEWOPENatok@%@appId@%@userId@%@{\"71285988327875351202\":{\"validUnit\":\"20201018142903\",\"validType\":\"1\"},\"68832914971891011760\":{\"validUnit\":\"25130610201034\",\"validType\":\"1\"},\"65876517902011041058\":{\"validUnit\":\"25130610201034\",\"validType\":\"2\"}}";
// final String tokenInfo = (String)redisUtils.get(validTokenKey);
// // Trace.logInfo(Trace.MODULE_COMMON, tokenInfo);
//
// // authInfo =
// //
// "NEWOPENatok@%@appId@%@userId@%@{\"71285988327875351202\":{\"validUnit\":\"20201018142903\",\"validType\":\"1\"},\"68832914971891011760\":{\"validUnit\":\"25130610201034\",\"validType\":\"1\"},\"65876517902011041058\":{\"validUnit\":\"25130610201034\",\"validType\":\"2\"}}";
// if (StringUtils.isBlank(tokenInfo) || "".equals(tokenInfo)) {
// throw new AccessControlException(ErrorEnum.oauthNotFoundTokenError.code(),
// ErrorEnum.oauthNotFoundTokenError.msg());
// }
// String tokenInfoDecode = new String(Base64.decode(tokenInfo.getBytes()));
// String[] tokenInfoArr = tokenInfoDecode.split("@%@", -1);
// if (tokenInfoArr.length != 4) {
// // token异常，重新授权登录
// throw new AccessControlException(ErrorEnum.oauthCheckTokenError.code(),
// ErrorEnum.oauthCheckTokenError.msg());
// // throw new AccessControlException("ERR22", "数据错误");
// }
// // 2.2校验传过来的token与服务器的token是否一致。不一致说明token过期或者是上送了错误的token，需要重新登录验证。
// // if(tokenInfo.equals(accessToken)) {
// if (!StringUtil.hasText(accessToken)) {
// throw new AccessControlException(ErrorEnum.oauthCheckTokenError.code(),
// ErrorEnum.oauthCheckTokenError.msg());
// }
// // Trace.logInfo(Trace.MODULE_COMMON, "3.验证服务是否授权");
// // 3.验证服务是否授权
// String productAuthJsonStr = tokenInfoArr[3];
// JSONObject productAuthJsonObj = JSONObject.parseObject(productAuthJsonStr);
// if (null == productAuthJsonStr || productAuthJsonStr.length() == 0) {
// // TODO:错误码配置
// throw new AccessControlException("Err0001", "有效期数据异常");
// }
// String productId = String.valueOf(apiInfo.get(Constants.PRD_ID));
// // {"65904700865144331621": {"validUnit": "20201018142903","validType": "1"}
// // "68832914971891011760": {"validUnit": "25130610201034", "validType": "1"}
// // "65876517902011041058": {"validUnit": "25130610201034", "validType": "2"}
//
// Object productInfoObj = productAuthJsonObj.get(productId);
// if (productInfoObj == null || !(productInfoObj instanceof Map)) {
// // TODO:错误码配置
// throw new AccessControlException("Err0002", "该服务未授权");
// }
//
// Map<String, String> productInfoMap = (Map<String, String>)productInfoObj;
// // 有效期
// String expireDateStr = productInfoMap.get("validUnit");
// // 授权类型 1单次有效 2阶段有效 3有效期有效
// final String validType = productInfoMap.get("validType");
// // 3.1未授权
// // http://14.36.0.243/open-oauth/index.html#/authorization:login
// // 前端沟通直接跳到授权页面参数需添加到 “#”前边,
// // 示例：http://14.36.0.243/open-oauth/index.html?secretStr=123&tpAppId=127297000002001&userId=123#/authorization:login
// if (StringUtils.isEmpty(expireDateStr)) {
// throw new AccessControlException(ErrorEnum.oauthServiceValidTimeError.code(),
// ErrorEnum.oauthServiceValidTimeError.msg());
// }
// DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
// LocalDateTime expireDate = LocalDateTime.parse(expireDateStr, dateTimeFormatter);
// // 3.2服务授权过期: 有效期<当前时间
// if (expireDate.compareTo(LocalDateTime.now()) < 0) {
//
// throw new AccessControlException(ErrorEnum.oauthAuthServiceTimeoutError.code(),
// ErrorEnum.oauthAuthServiceTimeoutError.msg());
// }
// // Trace.logInfo(Trace.MODULE_COMMON, "4.用户已登录授权服务，允许调用后端服务");
// return chain.filter(exchange).then((Mono
// .fromRunnable(() -> deleteServieAuthRecord(exchange, validType, validTokenKey, tokenInfo, productId))));
// }
//
// /**
// * 单次有效：调用一次后即过期，需要重新授权 调用接口结束后删除授权方式为单次有效的服务授权记录
// *
// * @param exchange
// * @return
// */
// private void deleteServieAuthRecord(ServerWebExchange exchange, String validType, String validTokenKey,
// String validTokenValue, String serviceId) {
// // 单次有效：调用一次后即删除授权服务，即使业务系统出错
// // Trace.logInfo(Trace.MODULE_COMMON, "5.调用服务后删除单次有效的授权记录 start...");
// // 1单次有效
// if ("1".equals(validType)) {
// // 获取解密的token
// String validInfo = new String(Base64.decode(validTokenValue.getBytes()));
//
// // 把这次单词授权的服务从token中删除
// String[] split = validInfo.split("@%@", -1);
// // 1.获取token做后一部分，即服务授权信息
// String serviceStr = split[3];
//
// JSONObject serviceObj =
// StringUtil.hasText(serviceStr) ? JSONObject.parseObject(serviceStr) : new JSONObject();
// // 2.移除此次调用单次授权的接口信息
// serviceObj.remove(serviceId);
// // 服务授权信息转换为String类型,并判断是否为空
// String serviceInfo = serviceObj.isEmpty() ? "" : JSONObject.toJSONString(serviceObj);
//
// // 最终token
// String newTokenStr = validInfo.substring(0, validInfo.lastIndexOf("@%@")) + "@%@" + serviceInfo;
// boolean result = redisUtils.set(validTokenKey,
// new String(Base64.encode(newTokenStr.getBytes())).replaceAll("\\r\\n", ""),
// redisUtils.getExpire(validTokenKey));
// // Trace.logInfo(Trace.MODULE_COMMON, "设置单次有效过期结果：{}", result);
// }
//
// }
//
// /**
// * token未失效但授权有效期失效了，生成一个新的随机数放在授权URL后
// */
// private String genH5AppIdRandom() {
// StringBuffer sb = new StringBuffer();
// Random random = new Random();
// for (int i = 0; i < 20; i++) {
// sb.append(random.nextInt(10));// .nextInt(99999999)
// }
// String randomStr = sb.toString();
// // Trace.logInfo(Trace.MODULE_COMMON, "新的openId映射随机数为：" + randomStr);
// String h5OpenId = (String)redisUtils.get("opengate_oauth_params_h5OpenId");
// redisUtils.set("opengate_h5OpenId_random_" + randomStr, h5OpenId, 900L);
// return randomStr;
// }
//
// }
